angular.module('usense.chat', [])

    .controller('ChatDetailCtrl', function ($scope, $stateParams, $state, Chat, $ionicScrollDelegate, $rootScope, $timeout, $ionicHistory, $ionicSideMenuDelegate) {
        var chatState = "disconnect";

        $scope.initChatDetail = function () {
            // 切换为list画面也可以用
            $scope.title = '聊天列表';
            $scope.chatDetail = {};
            $scope.chatDetail.chatId = 0;
            $scope.chatDetail.refresh = true;
            $scope.chatDetail.chatName = "";
            $scope.chatDetail.showHistoryMessageLink = true;
            $scope.chatDetail.fileSelected = false;
            $scope.chatDetail.scrollTopOrBottom = "bottom";
            $scope.chatDetail.users = "";
            $scope.chatDetail.messages = [];
            $scope.chatDetail.sendMsg = "";
        };

        $scope.$on( "$ionicView.enter", function( scopes, states ) {
            // 注意不能放在controller最后执行，此时view还没有ready
            if ($stateParams.chatId != 0) {

            }

            if ($rootScope.chatConfig.appName == 'nonghua') {
                if ($rootScope.user_access('view contact')) {
                    Chat.connect();
                } else {
                    if ($rootScope.user.uid == 0) {
                        alert("请登录或注册账户！");
                    } else {
                        alert("升级帐户后，您即可使用消息功能！");
                    }
                    $state.go('tabs.my-account'); //not working
                    //$ionicTabsDelegate.select(3);
                }
            } else {
                Chat.connect();
            }
        });

        $scope.toggleRight = function () {
            $ionicSideMenuDelegate.toggleRight();
        };

        $scope.exit = function () {
            Chat.disconnect();
            $ionicHistory.goBack();
        };

        $scope.goBack = function () {
            if ($ionicSideMenuDelegate.isOpen() && $stateParams.chatId == 0) {
                $scope.initChatDetail();
                $scope.toggleRight();
            } else {
                $scope.exit();
            }
        };

        $scope.$on('chat.disconnect', function (event) {
            //alert("连接中断...请重试.");
            $scope.exit();
        });

        $scope.openChatDetail = function (chatId, chatName) {
            var data = {
                chatId: chatId,
                chatName: chatName
            };
            $scope.chatDetail.chatId = chatId;
            $scope.chatDetail.chatName = chatName;
            $scope.chatDetail.refresh = true;
            $scope.title = chatName;
            if ($rootScope.chatConfig.appName == 'expert') {
                Chat.emit('customer', data);
            } else {
                if (!!$scope.chats[$scope.chatDetail.chatId]) {
                    var currentChat = Chat.chats[$scope.chatDetail.chatId];
                    // 设置聊天对象名
                    //$scope.title = getChatViewName(currentChat, $rootScope.user.uid);
                    $scope.chatDetail.users = currentChat.user;
                    $scope.chatDetail.messages = currentChat.messages;

                    // 刷新时间戳
                    Chat.emit('updateCheckpoint', {
                        chat_id: $scope.chatDetail.chatId,
                        user_id: $rootScope.user.uid
                    }, function (result) {
                        if (result.success) {
                            console.log('updateCheckpoint succeeded');
                        } else {
                            console.log('updateCheckpoint failed');
                        }
                    });

                    // 自动滚动到顶部或底部
                    if ($scope.chatDetail.scrollTopOrBottom == 'bottom') {
                        $timeout(function () {
                            $ionicScrollDelegate.$getByHandle('chat-handle').scrollBottom();
                        }, 100);
                    } else {
                        $timeout(function () {
                            $ionicScrollDelegate.$getByHandle('chat-handle').scrollTop();
                        }, 100);
                    }
                    $scope.chatDetail.scrollTopOrBottom = 'bottom';
                } else {
                    alert("会话不存在");
                    $scope.exit();
                }
            }
            $scope.toggleRight();
        };

        $scope.openChatList = function () {
            if ($rootScope.chatConfig.appName == 'nonghua') {
                if ($rootScope.isFarmer($rootScope.user.roles)) {
                    if ($scope.chatId % 2 == 0) {
                        Chat.emit('consult', "", function (result) {
                            if (result.success) {
                                console.log('consult sent successfully');
                            } else {
                                alert(result.reason);
                                $rootScope.goBack();
                            }
                        });
                    } else {
                        Chat.emit('complain', "", function (result) {
                            if (result.success) {
                                console.log('complain sent successfully');
                            } else {
                                alert(result.reason);
                                $rootScope.goBack();
                            }
                        });
                    }
                } else if ($rootScope.isEmployee($rootScope.user.roles)) {
                    // 如果是公司内部员工或者经销商，直接发送chats取得好友列表
                    Chat.emit('chats', "", function (result) {
                        if (result.success) {
                            console.log('chats sent successfully');
                        } else {
                            alert(result.reason);
                            $rootScope.goBack();
                        }
                    });
                }
            } else {
                Chat.emit('chats', null);
            }
        };

        $scope.getChatViewPic = function (chatValue, self) {
            if (chatValue.type == 0 || chatValue.type == 2) {
                var item = getChatViewItem(chatValue, self);
                if (item != null) {
                    return item.pic;
                }
                return null;
            } else if (chatValue.type == 1) {
                return chatValue.pic_url;
            } else {
                return null;
            }
        };

        $scope.getChatViewName = function (chatValue, self) {
            if (chatValue.type == 0 || chatValue.type == 2) {
                var item = getChatViewItem(chatValue, self);
                if (item != null) {
                    return item.name;
                }
                return null;
            } else if (chatValue.type == 1) {
                return chatValue.title;
            } else {
                return "匿名聊天";
            }
        };

        $scope.clearFileSelect = function () {
            var file = document.getElementById('file');
            file.value = "";
            $scope.sendMsg = "";
            $scope.fileSelected = false;
        };

        $scope.openFileDialog = function () {
            window.plugins.mfilechooser.open([], function (uri) {
                alert(uri);
                alert("mfilechooser");
            }, function (error) {
                alert(error);
            });
            alert("openFileDialog");
            if (!$scope.fileSelected) {
                ionic.trigger('click', {target: document.getElementById('file')});
            } else {
                $scope.clearFileSelect();
            }
        };

        $scope.onFileSelected = function (selectedFiles) {
            //console.log(selectedFiles);
            $scope.fileSelected = true;
            $scope.sendMsg = "[ ";
            for (var i = 0; i < selectedFiles.length; i++) {
                $scope.sendMsg += selectedFiles[i].name + " ";
            }
            $scope.sendMsg += "]";
            $scope.$apply();
        };

        $scope.$on('chat.ready', function (event) {
            if ($stateParams.chatId != 0) {
                $scope.openChatDetail($stateParams.chatId, $stateParams.chatName);
            } else {
                $scope.openChatList();
            }
        });

        $scope.$on('chat.update', function (event) {
            $scope.chats = Chat.chats;
            if (chatState == "disconnect") {
                chatState = "ready";
            }
            if ($scope.chatDetail.chatId != 0) {
                if (!!$scope.chats[$scope.chatDetail.chatId]) {
                    var currentChat = Chat.chats[$scope.chatDetail.chatId];
                    // 设置聊天对象名
                    //$scope.title = getChatViewName(currentChat, $rootScope.user.uid);
                    $scope.chatDetail.users = currentChat.user;
                    $scope.chatDetail.messages = currentChat.messages;

                    // 刷新时间戳
                    Chat.emit('updateCheckpoint', {
                        chat_id: $scope.chatDetail.chatId,
                        user_id: $rootScope.user.uid
                    }, function (result) {
                        if (result.success) {
                            console.log('updateCheckpoint succeeded');
                        } else {
                            console.log('updateCheckpoint failed');
                        }
                    });

                    // 自动滚动到顶部或底部
                    if ($scope.chatDetail.scrollTopOrBottom == 'bottom') {
                        $timeout(function () {
                            $ionicScrollDelegate.$getByHandle('chat-handle').scrollBottom();
                        }, 100);
                    } else {
                        $timeout(function () {
                            $ionicScrollDelegate.$getByHandle('chat-handle').scrollTop();
                        }, 100);
                    }
                    $scope.chatDetail.scrollTopOrBottom = 'bottom';
                } else {
                    alert("会话不存在");
                    $scope.exit();
                }
            }
            else {

            }
            $scope.$apply();
        });

        $scope.loadHistory = function (chatId, detailMessages) {
            if (chatState == "ready" && $scope.chatDetail.chatId != 0) {
                $scope.chatDetail.scrollTopOrBottom = 'top';
                var minMessageId = detailMessages.length > 0 ? detailMessages[0].message_id : 0;
                var info = {
                    chat_id: chatId,
                    message_id: minMessageId
                };
                Chat.emit('historyMessages', info, function (result) {
                    console.log(result);
                    if (result.success) {
                        for (var i = 0; i < result.historyMessages.length; i++) {
                            $scope.chatDetail.messages.unshift(result.historyMessages[i]);
                        }
                    } else {
                        alert(result.reason);
                    }
                });
            } else {
                alert("系统繁忙，请稍后！");
                $scope.exit();
            }
        };

        $scope.sendMessageOrFile = function () {
            if (chatState == "ready" && $scope.chatDetail.chatId != 0) {
                if (!$scope.chatDetail.fileSelected && !!$scope.chatDetail.sendMsg) {
                    var content = replaceSpecials($scope.chatDetail.sendMsg);
                    if (content.length == 0) {
                        return;
                    }
                    if (content.length > 255) {
                        alert('消息必须在140字以内');
                        return;
                    }
                    // 发送消息
                    var message = {
                        'chat_id': $scope.chatDetail.chatId,
                        'content': content
                    };
                    Chat.emit('message', message, function (result) {
                        console.log(result);
                        if (result.success) {
                            $scope.chatDetail.sendMsg = '';
                            $scope.chatDetail.messages.push({
                                'message_id': result.message_id,
                                'sender_id': $rootScope.user.uid,
                                'content': content,
                                'timestamp': result.timestamp
                            });
                            $scope.chatDetail.scrollTopOrBottom = 'bottom';
                            $timeout(function () {
                                $ionicScrollDelegate.$getByHandle('chat-handle').scrollBottom();
                            }, 100);
                        } else {
                            alert(result.reason);
                        }
                    });
                } else if ($scope.chatDetail.fileSelected) {
                    var file = document.getElementById('file').files[0];
                    if (file == null || file.size <= 0) {
                        //alert(JSON.stringify(file));
                        //alert('请输入文字或选择文件上传');
                        $scope.clearFileSelect();
                        return;
                    }
                    if (file.size >= 5000000) {
                        alert('文件大小不能超过5M');
                        $scope.clearFileSelect();
                        return;
                    }
                    Chat.upload('file', file, {
                        chat_id: $scope.chatDetail.chatId,
                        uid: $rootScope.user.uid,
                        name: file.name,
                        size: file.size
                    }, function (result) {
                        console.log(result);
                        if (result.success) {
                            $scope.uploadFile = '';
                            $scope.chatDetail.messages.push({
                                'message_id': result.message_id,
                                'sender_id': $rootScope.user.uid,
                                'content': result.content,
                                'timestamp': result.timestamp
                            });
                            $scope.chatDetail.scrollTopOrBottom = 'bottom';
                            $timeout(function () {
                                $ionicScrollDelegate.$getByHandle('chat-handle').scrollBottom();
                            }, 100);
                        } else {
                            alert(result.reason);
                        }
                    });
                    $scope.clearFileSelect();
                }
            } else {
                alert("系统繁忙，请稍后！");
                $scope.exit();
            }
        };

        $scope.initChatDetail();
    })

    .factory('Chat', function ($rootScope, $timeout) {
        var socket;
        var status = "disconnect";
        var chats = null;
        var uid = null;
        var timeout_promise = null;

        return {
            connect: function () {
                var chat_object = this;
                if (status == "disconnect") {
                    socket = null;
                    socket = io.connect($rootScope.chatConfig.serverAddr, {
                        transports: ['websocket'],
                        'force new connection': 'true'
                    });

                    socket.on('ready', function (data) {
                        status = "ready";
                        $rootScope.$broadcast('chat.ready');
                    });

                    socket.on('disconnect', function () {
                        status = "disconnect";
                        $rootScope.$broadcast('chat.disconnect');
                    });

                    socket.on('connect', function () {
                        //alert("connected!");
                        if (timeout_promise) {
                            $timeout.cancel(timeout_promise);
                        }
                        $rootScope.$broadcast('chat.connected');
                    });

                    // 初始时开始监听chats消息，接收列表及初始消息
                    socket.on('chats', function (data) {
                        chat_object.chats = data.chats;
                        chat_object.uid = data.uid;
                        $rootScope.$broadcast('chat.update');
                    });

                    // 监听新消息
                    socket.on('message', function (data) {
                        var message_id = data.message_id;
                        var chat_id = data.chat_id;
                        var sender_id = data.sender_id;
                        var content = data.content;
                        var timestamp = data.timestamp;
                        console.log(data);

                        if (!!chat_object.chats[chat_id]) {
                            chat_object.chats[chat_id]['messages'].push({
                                'message_id': message_id,
                                'sender_id': sender_id,
                                'content': content,
                                'timestamp': timestamp
                            });
                        }
                        $rootScope.$broadcast('chat.update');
                    });

                    // 监听错误消息
                    socket.on('errors', function (data) {
                        var error_no = data.error_no;
                        var message = data.message;

                        alert('错误[' + error_no + ']: ' + message);

                        if (error_no == '10003') {
                            status = "disconnect";
                            $rootScope.$broadcast('chat.disconnect');
                        }
                    });

                    timeout_promise = $timeout(function () {
                        socket.disconnect();
                        status = "disconnect";
                        alert("连接超时！");
                        $rootScope.$broadcast('chat.disconnect');
                    }, 5000);
                }
                if (status == "ready") {
                    $rootScope.$broadcast('chat.ready');
                }
            },
            //on: function (eventName, callback) {
            //    socket.on(eventName, function () {
            //        var args = arguments;
            //        if (!disconnect) {
            //            $rootScope.$apply(function () {
            //                callback.apply(socket, args);
            //            });
            //        }
            //    });
            //},
            emit: function (eventName, data, callback) {
                socket.emit(eventName, data, function () {
                    var args = arguments;
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback.apply(socket, args);
                        }
                    });
                });
            },
            upload: function (eventName, file, data, callback) {
                var stream = ss.createStream();
                ss(socket).emit(eventName, stream, data, function () {
                    var args = arguments;
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback.apply(socket, args);
                        }
                    });
                });

                var blobStream = ss.createBlobReadStream(file);
                var size = 0;
                blobStream.on('data', function (chunk) {
                    size += chunk.length;
                    console.log(Math.floor(size / file.size * 100) + '%');
                }).on('end', function () {
                    console.log('文件传输完成');
                    stream.end();
                });
                blobStream.pipe(stream);
            },
            disconnect: function () {
                socket.disconnect();
                status = "disconnect";
            },
            chats: chats,
            uid: uid
        }
    })

    .directive('lastMessage', function () {
        var directive = {};
        directive.restrict = 'E';
        directive.scope = {
            messages: "=",
            users: "=",
            selfId: "@",
            chatId: "=",
            currentChatId: "=",
            index: '='
        };
        //directive.template = '<div class="meta__sub--dark">{{chat.sender_name}}: {{chat.content}} 于 {{chat.timestamp | date:"yyyy-MM-dd HH:mm:ss"}}</div>';
        directive.template = '<div class="meta__sub--dark"></div>';
        //directive.template = '<div class="meta__sub--dark"></div>';
        directive.link = function (scope, element, attrs) {
            scope.$watch('messages', messageListener, true);
            scope.$on('clearState', function (e, args) {
                if (e.currentScope.index == args.index) {
                    clearUnreadMessageState(element.children("div"));
                }
            });

            function messageListener(newModel, oldModel, scope) {
                var messages = scope.messages;
                var users = scope.users;
                var selfId = scope.selfId;
                var chatId = scope.chatId;
                var currentChatId = scope.currentChatId;

                var maxMessageId = 0;
                for (var key in messages) {
                    if (key > maxMessageId) {
                        maxMessageId = key;
                    }
                }

                if (maxMessageId != 0) {
                    var date = new Date(messages[maxMessageId].timestamp);
                    element.children("div").html(recognizeUser(selfId, messages[maxMessageId].sender_id) +
                        (isToday(date) ? date.toLocaleTimeString() : date.toLocaleDateString()) + ' ' + truncateMessage(messages[maxMessageId].content));
                    if (chatId != currentChatId) {
                        setUnreadMessageState(element.children("div"));
                    }
                }
            }
        };

        return directive;
    })

    .directive('messageData', function () {
        var directive = {};
        directive.restrict = 'A';
        directive.scope = {
            detailMessages: "=",
            detailUsers: "=",
            refresh: "=",
            scroll: "=",
            selfId: "@"
        };

        directive.link = function (scope, element, attrs) {
            scope.$watch('detailMessages', messageListener, true);
            // TODO: May add another listener on detailUsers if users can change on the fly.

            function messageListener(newModel, oldModel, scope) {
                var selfId = scope.selfId;
                var detailMessages = scope.detailMessages;
                var detailUsers = scope.detailUsers;
                var scrollTopOrBottom = scope.scroll;

                if (scope.refresh) {
                    element.empty();
                    scope.refresh = false;
                }

                var templateHtmlForSelf =
                    '<div class="message--send">' +
                    '<figure class="message__avatar_send">' +
                    '   <img src="@imgURI" />' +
                    '</figure>' +
                    '<div class="message__bubble--send">@messageBody</div>' +
                    '</div>' +
                    '<div class="cf"></div>';
                var templateHtmlForOthers =
                    '<div class="message">' +
                    '<figure class="message__avatar">' +
                    '   <img src="@imgURI" />' +
                    '</figure>' +
                    '<div class="message__bubble">@messageBody</div>' +
                    '</div>' +
                    '<div class="cf"></div>';
                var whoseId = null;

                if (!!selfId) {
                    if (scope.scroll == "bottom") {
                        for (var i = oldModel.length; i < newModel.length; i++) {
                            whoseId = newModel[i].sender_id;
                            if (whoseId == selfId) {
                                element.append(templateHtmlForSelf.replace('@messageBody', alterLinkContent(newModel[i].content))
                                    .replace('@imgURI', detailUsers[selfId].pic));
                            } else {
                                element.append(templateHtmlForOthers.replace('@messageBody', alterLinkContent(newModel[i].content))
                                    .replace('@imgURI', (!!detailUsers[whoseId]) ? detailUsers[whoseId].pic : null));
                            }
                        }
                    } else {
                        for (var i = newModel.length - oldModel.length - 1; i >= 0; i--) {
                            whoseId = newModel[i].sender_id;
                            if (whoseId == selfId) {
                                element.prepend(templateHtmlForSelf.replace('@messageBody', alterLinkContent(newModel[i].content))
                                    .replace('@imgURI', detailUsers[selfId].pic));
                            } else {
                                element.prepend(templateHtmlForOthers.replace('@messageBody', alterLinkContent(newModel[i].content))
                                    .replace('@imgURI', (!!detailUsers[whoseId]) ? detailUsers[whoseId].pic : null));
                            }
                        }
                    }
                }
            }
        };

        return directive;
    })

    .directive("onFileChanged", [function () {
        return {
            scope: {
                onFileChanged: "="
            },
            link: function (scope, element, attributes) {
                element.bind("change", function (changeEvent) {
                    scope.onFileChanged(changeEvent.target.files);
                });
            }
        }
    }]);


function recognizeUser(senderId, selfId) {
    if (senderId != selfId) {
        return '';
    } else {
        return '[我] ';
    }
}

function truncateMessage(message) {
    if (!!message) {
        var strs = new Array();
        strs = message.split("<br>");

        if (strs[0].length >= 10 || message.indexOf("<br>") > 0) {
            return mySubstring(strs[0], 14) + '...';
        } else {
            return strs[0];
        }
    } else {
        return '';
    }
}

function mySubstring(str, n) {
    var r = /[^\x00-\xff]/g;
    if (str.replace(r, "mm").length <= n) {
        return str;
    }
    var m = Math.floor(n / 2);
    for (var i = m; i < str.length; i++) {
        if (str.substr(0, i).replace(r, "mm").length >= n) {
            return str.substr(0, i);
        }
    }
    return str;
}

function alterLinkContent(content) {
    if (content.indexOf("http://") >= 0 || content.indexOf("https://") >= 0) {
        if (content.lastIndexOf(".png") >= 0 || content.lastIndexOf(".jpg") >= 0 || content.lastIndexOf(".bmp") >= 0) {
            return '<img onclick="window.open(\'' + content + '\',\'_blank\',\'location=yes\', \'closebuttoncaption=返回\')" src="' + content + '" width="100%">';
        } else {
            return '<a onclick="window.open(\'' + content + '\',\'_blank\',\'location=yes\', \'closebuttoncaption=返回\')">' + content + '</a>';
        }
    } else {
        return content;
    }
}

function setUnreadMessageState(element) {
    element.css('color', 'blue');
    //element.css('font-weight', 'bold');
}

function clearUnreadMessageState(element) {
    element.css('color', 'grey');
    //element.css('font-weight', '');
}

function isToday(d) {
    var n = new Date();
    if (d.toDateString() == n.toDateString()) {
        return true;
    } else {
        return false;
    }
}

function replaceSpecials (val) {
    var regN = /\n/g;
    return val.replace(regN, "<br>");
}

function getChatViewItem (chatValue, self) {
    // TODO: need another property to distinguish group and individual
    for (var key in chatValue.user) {
        if (!!key && key != self) {
            return chatValue.user[key];
        }
    }
    return null;
}

function getChatViewName (chatValue, self) {
    if (chatValue.type == 0 || chatValue.type == 2) {
        var item = getChatViewItem(chatValue, self);
        if (item != null) {
            return item.name;
        }
        return null;
    } else if (chatValue.type == 1) {
        return chatValue.title;
    } else {
        return "匿名聊天";
    }
}

function getChatViewPic (chatValue, self) {
    if (chatValue.type == 0 || chatValue.type == 2) {
        var item = getChatViewItem(chatValue, self);
        if (item != null) {
            return item.pic;
        }
        return null;
    } else if (chatValue.type == 1) {
        return chatValue.pic_url;
    } else {
        return null;
    }
}
